package xworker.gluon.xapp.views;

import com.gluonhq.charm.glisten.control.ExceptionDialog;
import javafx.application.Platform;
import org.xmeta.ActionContext;
import org.xmeta.Thing;
import org.xmeta.World;
import org.xmeta.annotation.ActionField;
import org.xmeta.util.UtilString;
import xworker.protobuf.ProtobufMessageFactory;
import xworker.gluon.netty.ClientClient;
import xworker.gluon.netty.protocols.GluonMessages;
import xworker.javafxcontrol.thing.form.ThingForm;
import xworker.lang.executor.Executor;

import java.util.Map;

public class NetworkView {
    private static final String TAG = NetworkView.class.getName();

    @ActionField
    public javafx.scene.control.Button connectServerButton;
    @ActionField
    public javafx.scene.control.Button disconnectButton;
    @ActionField
    public ThingForm providerForm;
    @ActionField
    public javafx.scene.control.Button registButton;
    @ActionField
    public ThingForm serverForm;
    @ActionField
    public javafx.scene.control.Label registLabel;

    public NetworkView(){
        Thing thing = World.getInstance().getThing("xworker.gluon.netty.ClientClient/@Handlers/@SelfProtobufDecoder/@ProtobufMessageFactory");
        ProtobufMessageFactory messageFactory = thing.doAction("getProtobufMessageFactory", new ActionContext());
        messageFactory.regist(GluonMessages.class);

        messageFactory.registBuilderFactory("HeartBeat", xworker.gluon.netty.protocols.GluonMessages.HeartBeat::newBuilder);
        messageFactory.registBuilderFactory("SendThingToClientResp", xworker.gluon.netty.protocols.GluonMessages.SendThingToClientResp::newBuilder);
        messageFactory.registBuilderFactory("ClientReceiveThing", xworker.gluon.netty.protocols.GluonMessages.ClientReceiveThing::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$SendThingToClientResp", xworker.gluon.netty.protocols.GluonMessages.SendThingToClientResp::newBuilder);
        messageFactory.registBuilderFactory("RegistProviderResp", xworker.gluon.netty.protocols.GluonMessages.RegistProviderResp::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$HeartBeat", xworker.gluon.netty.protocols.GluonMessages.HeartBeat::newBuilder);
        messageFactory.registBuilderFactory("ConnectProviderResp", xworker.gluon.netty.protocols.GluonMessages.ConnectProviderResp::newBuilder);
        messageFactory.registBuilderFactory("ConnectProviderReq", xworker.gluon.netty.protocols.GluonMessages.ConnectProviderReq::newBuilder);
        messageFactory.registBuilderFactory("ListClientsReq", xworker.gluon.netty.protocols.GluonMessages.ListClientsReq::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$ClientReceiveThing", xworker.gluon.netty.protocols.GluonMessages.ClientReceiveThing::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$ConnectProviderResp", xworker.gluon.netty.protocols.GluonMessages.ConnectProviderResp::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$RegistProviderResp", xworker.gluon.netty.protocols.GluonMessages.RegistProviderResp::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$ListClientsResp", xworker.gluon.netty.protocols.GluonMessages.ListClientsResp::newBuilder);
        messageFactory.registBuilderFactory("ListClientsResp", xworker.gluon.netty.protocols.GluonMessages.ListClientsResp::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$Client", xworker.gluon.netty.protocols.GluonMessages.Client::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$ConnectProviderReq", xworker.gluon.netty.protocols.GluonMessages.ConnectProviderReq::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$ListClientsReq", xworker.gluon.netty.protocols.GluonMessages.ListClientsReq::newBuilder);
        messageFactory.registBuilderFactory("Client", xworker.gluon.netty.protocols.GluonMessages.Client::newBuilder);
        messageFactory.registBuilderFactory("SendThingToClientReq", xworker.gluon.netty.protocols.GluonMessages.SendThingToClientReq::newBuilder);
        messageFactory.registBuilderFactory("RegistProviderReq", xworker.gluon.netty.protocols.GluonMessages.RegistProviderReq::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$RegistProviderReq", xworker.gluon.netty.protocols.GluonMessages.RegistProviderReq::newBuilder);
        messageFactory.registBuilderFactory("xworker.gluon.netty.protocols.GluonMessages$SendThingToClientReq", xworker.gluon.netty.protocols.GluonMessages.SendThingToClientReq::newBuilder);
    }

    public void init(){
        connectServerButton.disableProperty().bind(ClientClient.networkStatus);
        disconnectButton.disableProperty().bind(ClientClient.networkStatus.not());
        registButton.disableProperty().bind(ClientClient.networkStatus.not());
        ClientClient.registStatus.addListener((observable, oldValue, newValue) -> Platform.runLater(() ->{
            if(newValue){
                registLabel.setText(UtilString.getString("lang:d=已注册!&en=Registered!", new ActionContext()));
                registButton.setDisable(true);
            }else{
                registLabel.setText(UtilString.getString("lang:d=未注册!&en=Not register!", new ActionContext()));
                registButton.setDisable(false);
            }
        }));
    }

    public void connectServer(){
        Map<String, Object> values = serverForm.getValues();
        Executor.info(TAG, "Connect to server, params=" + values);
        new Thread(() -> {
            ClientClient.connect((String) values.get("host"), Integer.parseInt((String) values.get("port")));
        }).start();
    }

    public void disconnectServer(){
        Executor.info(TAG, "Disconnect server");
        ClientClient.disconnect();
    }

    public void registProvider(){
        try {
            Map<String, Object> values = providerForm.getValues();
            Executor.info(TAG, "Regist to provider, params=" + values);

            ClientClient.name = (String) values.get("myName");
            ClientClient.providerName = (String) values.get("providerName");
            ClientClient.providerPassword = (String) values.get("providerPassword");

            GluonMessages.ConnectProviderReq.Builder builder = GluonMessages.ConnectProviderReq.newBuilder();
            builder.setClientName(ClientClient.name);
            builder.setName(ClientClient.providerName);
            builder.setPassword(ClientClient.providerPassword);

            ClientClient.sendMessage(builder.build());
        }catch(Exception e){
            ExceptionDialog dialog = new ExceptionDialog();
            dialog.setException(e);
            dialog.showAndWait();
        }
    }

    public static void main(String[] args){
        try{
            World world = World.getInstance();
            world.init("./xworker/");

            Thing thing = World.getInstance().getThing("xworker.gluon.netty.ClientClient/@Handlers/@SelfProtobufDecoder/@ProtobufMessageFactory");
            ProtobufMessageFactory factory = thing.doAction("getProtobufMessageFactory", new ActionContext());
            System.out.println(factory.generateBuilderFactoryCode());

        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
